﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DVPCameraType;
using System.IO;
using System.Threading;
using HalconDotNet;
using DataCodeDemo.Operators;
using DataCodeDemo.CamDrives;
using DataCodeDemo.Servers;
using System.Drawing.Imaging;

namespace DataCodeDemo
{
    public partial class Home : Form
    {
        /// <summary>
        /// 相机句柄
        /// </summary>
        public uint m_handle = 0;

        private bool _manualTestFlag;

        private ICam _cam;

        private List<CameraInfos> cameraInfos;

        private HControlManager _halconControlManager;
        // private HImage hImage;

        //private HDataCode2D hDataCode2D;

        private HXLDCont hXLDCont;

        // private HTuple decodedDataStrings;

        private string _path_datacode = "..\\..\\DMFile\\dm1.dcm";

        CancellationTokenSource cts = new CancellationTokenSource();

        private bool _online;
        /// <summary>
        /// 联机
        /// </summary>
        public bool Online
        {
            get { return _online; }
            set
            {
                _online = value;
                if (value)
                {
                    //Server.recvFunc = new Func<byte[], string>(ServerRecv);
                }
                else
                {
                    //Server.recvFunc = null;
                }
            }
        }


        public Home()
        {
            InitializeComponent();
            _halconControlManager = new HControlManager(hWindowControl1);
            fileSystemWatcher1.Changed += FileSystemWatcher1_Changed;
            FileSystemWatcher1_Changed(null, null);
            //Server.SocketServie();
            //Server.recvFunc = new Func<byte[], string>(ServerRecv);

            _cam = new DVPCamUsbDrive();
            OperateResult<List<CameraInfos>> result = _cam.GetCameras();
            if (result.IsSuccess)
            {
                cameraInfos = result.Content;
                _cam.OpenCam(cameraInfos[0]);
            }

        }

        public string ServerRecv(byte[] data)
        {
            string recvStr = Encoding.UTF8.GetString(data).Replace("\0", "");
            if (recvStr == "T")
            {
                //触发拍照，目前测试时从相册导入
                //int index = int.Parse(lbCurrentNum.Text);
                //DirectoryInfo info = new DirectoryInfo(fileSystemWatcher1.Path);
                //var file = info.GetFiles()[index - 1];
                //HImage hImage = new HImage(file.FullName);
                //单次处理
                HImage hImage = AcqImage2();
                if (hImage.IsInitialized())
                {
                    return OneShot(hImage);
                }
                else
                {
                    return string.Empty;
                }

            }
            else return string.Empty;
        }


        private void FileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
        {
            try
            {
                DirectoryInfo info = new DirectoryInfo(fileSystemWatcher1.Path);
                lbImageInputNum.Text = info.GetFiles().Length.ToString();
            }
            catch (Exception ex)
            {

            }

        }

        private void btnPropertyModal_Click(object sender, EventArgs e)
        {
            _cam.ShowPropertyModalDialog(Handle);
        }

        /// <summary>
        /// 检查相机句柄是否有效
        /// 相机句柄在打开相机后赋唯一值
        /// </summary>
        /// <param name="handle">相机句柄</param>
        /// <returns></returns>
        public bool IsValidHandle(uint handle)
        {
            bool bValidHandle = false;
            dvpStatus status = DVPCamera.dvpIsValid(handle, ref bValidHandle);
            if (status == dvpStatus.DVP_STATUS_OK)
            {
                return bValidHandle;
            }
            return false;
        }

        private void btnOn_Off_Click(object sender, EventArgs e)
        {
            string tmp = Online ? "脱机" : "联机";
            DialogResult res = MessageBox.Show($"确定{tmp}？", "联机/脱机", MessageBoxButtons.OKCancel);
            if (res == DialogResult.OK)
            {
                if (Online)
                {
                    btnOn_Off.BackColor = Color.White;
                    Online = false;
                }
                else
                {
                    btnOn_Off.BackColor = Color.Green;
                    Online = true;
                }
            }
        }

        private void btnImageFile_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog
            {
                Description = "请选择输入图像文件夹"
            };
            if (dialog.ShowDialog() == DialogResult.OK || dialog.ShowDialog() == DialogResult.Yes)
            {
                txtImageInputFolder.Text = dialog.SelectedPath;
                fileSystemWatcher1.Path = dialog.SelectedPath;
                FileSystemWatcher1_Changed(null, null);
            }
        }

        private void btnTest_Click(object sender, EventArgs e)
        {
            if (_manualTestFlag)
            {
                btnTest.BackColor = Color.White;
                _manualTestFlag = false;
                cts?.Cancel();
            }
            else
            {
                btnTest.BackColor = Color.Yellow;
                _manualTestFlag = true;
                cts = new CancellationTokenSource();
                cts.Token.Register(() => { });
                Task manualTestTask = new Task(ManualTest, cts.Token);
                Task manualTestBtnReset = manualTestTask.ContinueWith(new Action<Task>((t) => { btnTest_Click(null, null); }));
                manualTestTask.Start();
            }
        }

        public void ManualTest()
        {
            int index = int.Parse(lbCurrentNum.Text);
            int totalNum = int.Parse(lbImageInputNum.Text);
            if (index <= 0 || index > totalNum) return;
            DirectoryInfo info = new DirectoryInfo(fileSystemWatcher1.Path);
            if (info.GetFiles().Length == 0) return;
            while (index > 0 && index <= totalNum)
            {
                if (cts.Token.IsCancellationRequested) return;
                Invoke(new Action(() =>
                {
                    lbCurrentNum.Text = index.ToString();
                }));
                var file = info.GetFiles()[index - 1];
                HImage hImage = new HImage(file.FullName);
                OneShot(hImage);
                index++;
                totalNum = Int32.Parse(lbImageInputNum.Text);
                Thread.Sleep(300);
            }

        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            sslProcessImageNum.Text = "0";
            sslOKNum.Text = "0";
        }

        public void Disp_Text(HWindow win, int Row, int Column, string color, string text)
        {
            try
            {
                //设置字体颜色
                win.SetColor(color);
                //设置字体风格
                //win.SetFont("Courier-Bold-20");
                //设置显示的位置（坐标）
                win.SetTposition(Row, Column);
                //设置显示的内容
                win.WriteString(text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnForward_Click(object sender, EventArgs e)
        {
            int index = Int32.Parse(lbCurrentNum.Text);
            int totalNum = Int32.Parse(lbImageInputNum.Text);
            index++;
            if (index <= 0 || index > totalNum) return;
            Invoke(new Action(() =>
            {
                lbCurrentNum.Text = index.ToString();
            }));
            DirectoryInfo info = new DirectoryInfo(fileSystemWatcher1.Path);
            if (info.GetFiles().Length == 0) return;
            var file = info.GetFiles()[index - 1];
            HImage hImage = new HImage(file.FullName);
            OneShot(hImage);
        }

        private string OneShot(HImage hImage)
        {
            string result = string.Empty;
            FindParams findParams = new FindParams
            {
                SqClosingRedius = double.Parse(txtSqClosing.Text),
                SqMinArea = double.Parse(txtSqMinArea.Text),
                SqExpansion = int.Parse(txtSqExpansion.Text),
                PointExpansion = int.Parse(txtPointExpansion.Text),
                FindNum = int.Parse(txtFindNum.Text)
            };
            _halconControlManager.HImage = hImage;
            DataCodeResult dataCodeResult = HalconOperator.FindDataCode(hImage, _path_datacode, findParams);
            sslProcessImageNum.Text = (long.Parse(sslProcessImageNum.Text) + 1).ToString();
            if (dataCodeResult.HXLDConts.CountObj() > 0)
            {
                _halconControlManager.HXLDInfos.Add(new HXLDInfo { Color = "green", HXLD = dataCodeResult.HXLDConts, LineWidth = 5 });
                for (int i = 0; i < dataCodeResult.HXLDConts.CountObj(); i++)
                {
                    dataCodeResult.HXLDConts[i + 1].SmallestCircleXld(out double row1, out double col1, out double radius1);//计算当前线条的中心和半径
                    _halconControlManager.TextInfos.Add(new TextInfo
                    {
                        Color = "green",
                        Text = dataCodeResult.DecodedDataStrings.TupleSelect(0),
                        Location = new Point((int)(row1 + radius1), (int)col1)
                    });//添加要显示的文字

                    if (i == 0)
                    {
                        result = dataCodeResult.DecodedDataStrings.TupleSelect(0);
                    }
                    else
                    {
                        result += "," + dataCodeResult.DecodedDataStrings.TupleSelect(i);
                    }
                }
                sslOKNum.Text = (long.Parse(sslOKNum.Text) + 1).ToString();
            }
            hImage?.Dispose();
            GC.Collect();
            return result;
        }

        private void btnResetNum_Click(object sender, EventArgs e)
        {
            lbCurrentNum.Text = "1";
        }

        private void btnBackward_Click(object sender, EventArgs e)
        {
            int index = int.Parse(lbCurrentNum.Text);
            int totalNum = int.Parse(lbImageInputNum.Text);
            index--;
            if (index <= 0 || index > totalNum) return;
            Invoke(new Action(() =>
            {
                lbCurrentNum.Text = index.ToString();
            }));

            DirectoryInfo info = new DirectoryInfo(fileSystemWatcher1.Path);
            if (info.GetFiles().Length == 0) return;
            var file = info.GetFiles()[index - 1];
            HImage hImage = new HImage(file.FullName);
            OneShot(hImage);
        }

        private void Home_FormClosed(object sender, FormClosedEventArgs e)
        {
            tcpServer?.Stop();
            tcpClient?.Stop();
            Environment.Exit(0);
        }

        private void btnTrigger_Click(object sender, EventArgs e)
        {
            HImage hImage = AcqImage2();
            if (hImage.IsInitialized())
            {
                OneShot(hImage);
            }
        }

        private bool _isLive;
        private void btnLive_Click(object sender, EventArgs e)
        {
            _isLive = !_isLive;
            if (_isLive)
            {
                Thread liveTh = new Thread(LiveCam);
                liveTh.Start();
            }           
        }

        private void LiveCam()
        {
            while (true)
            {
                if (!_isLive) break;
                HImage hImage = AcqImage2();
                if (hImage.IsInitialized())
                {
                    _halconControlManager.HImage = hImage;
                }
                Thread.Sleep(1);
            }
        }
        //private HImage AcqImage()
        //{
        //    OperateResult<ImageInfo> result = _cam.AcquireImage();
        //    HImage hImage = new HImage();
        //    if (result.IsSuccess)
        //    {
        //        ImageInfo imageInfo = result.Content;
        //        int width = imageInfo.FrameInfo.iWidth;
        //        int height = imageInfo.FrameInfo.iHeight;
        //        //图像是否旋转了90度，旋转了90度帧宽度和高度要互换
        //        if (imageInfo.FrameInfo.bRotateState != false)
        //        {
        //            height = imageInfo.FrameInfo.iWidth;
        //            width = imageInfo.FrameInfo.iHeight;
        //        }
        //        if (imageInfo.FrameInfo.format == zwxImageFormat.FORMAT_BGR24)
        //        {
        //            hImage.GenImageInterleaved(imageInfo.ImageBuffer, "bgr", width, height, 0, "byte", 0, 0, 0, 0, -1, 0);
        //        }
        //        else if (imageInfo.FrameInfo.format == zwxImageFormat.FORMAT_MONO)
        //        {
        //            hImage.GenImage1Extern("byte", width, height, imageInfo.ImageBuffer, new IntPtr());
        //        }
        //    }
        //    else
        //    {
        //        hImage?.Dispose();
        //    }
        //    return hImage;
        //}

        private HImage AcqImage2()
        {
            OperateResult<Bitmap> result = _cam.AcquireImage2();
            HImage hImage = new HImage();
            if (result.IsSuccess)
            {
                Bitmap bitmap = result.Content;
                Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadWrite, bitmap.PixelFormat);
                if (bitmapData.PixelFormat == PixelFormat.Format8bppIndexed)
                {
                    hImage.GenImage1("byte", bitmap.Width, bitmap.Height, bitmapData.Scan0);
                }
                else if (bitmapData.PixelFormat == PixelFormat.Format24bppRgb)
                {
                    //int byteWidthg = bitmapData.Stride / 3;
                    //byte[] imageR = new byte[byteWidthg * bitmapData.Height];
                    //byte[] imageG = new byte[byteWidthg * bitmapData.Height];
                    //byte[] imageB = new byte[byteWidthg * bitmapData.Height];
                    //unsafe
                    //{
                    //    byte* ptr = (byte*)bitmapData.Scan0;
                    //    for (int i = 0; i < bitmapData.Height; i++)
                    //    {
                    //        for (int j = 0; j < bitmapData.Width; j++)
                    //        {
                    //            imageB[i * byteWidthg + j] = *(ptr + 0);
                    //            imageG[i * byteWidthg + j] = *(ptr + 1);
                    //            imageR[i * byteWidthg + j] = *(ptr + 2);
                    //            ptr += 3;
                    //        }
                    //        ptr += bitmapData.Stride - bitmapData.Width * 3;
                    //    }
                    //    fixed (byte* pR = imageR, pG = imageG, pB = imageB)
                    //    {
                    //        hImage.GenImage3("byte", bitmapData.Width, bitmapData.Height, new IntPtr(pR), new IntPtr(pG), new IntPtr(pB));
                    //    }
                    //}
                    hImage.GenImageInterleaved(bitmapData.Scan0, "bgr", bitmap.Width, bitmap.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
                }
                else hImage?.Dispose();
                bitmap.UnlockBits(bitmapData);
                bitmap?.Dispose();
            }
            else
            {
                hImage?.Dispose();
            }
            return hImage;
        }
        SocketTcpServer tcpServer = new SocketTcpServer();
        SocketTcpClient tcpClient = new SocketTcpClient(true);
        private void button1_Click(object sender, EventArgs e)
        {          
            tcpClient.InitSocket("127.0.0.1", 60000);
            tcpClient.OnRecvMsg += TcpClient_OnReceiveMsg;
            tcpClient?.Start();
            tcpServer.InitSocket("127.0.0.1", 3000);
            tcpServer.OnRecvMsg += TcpServer_OnReceiveMsg;
            tcpServer?.Start();
        }

        private void TcpServer_OnReceiveMsg(object sender, RecvMsgEventArgs e)
        {
            tcpServer?.Send(e.ClientSocket, e.Msg);
        }

        private void TcpClient_OnReceiveMsg(object sender, RecvMsgEventArgs e)
        {
            tcpClient?.Send(e.Msg);
        }
    }


}
